home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / util3 / cdt10.lha / CDT / source / cdt.c < prev    next >
C/C++ Source or Header  |  1995-11-24  |  21KB  |  646 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /* CDT - a small shell utility to deal with a CD-ROM (based on SCSIutil ;) */
  4. /*     - written by Gunther Nikl in 11/1995                                */
  5. /*     - can *only* be compiled with gcc ...                               */
  6. /*                                                                         */
  7. /***************************************************************************/
  8.  
  9. /***************************************************************************/
  10. /*                                                                         */
  11. /* includes                                                                */
  12. /*                                                                         */
  13. /***************************************************************************/
  14.  
  15. #include <exec/types.h>
  16.  
  17. #ifndef CONST
  18. #define CONST const
  19. #endif
  20. #ifndef INLINE
  21. #define INLINE inline
  22. #endif
  23.  
  24. #include <exec/io.h>
  25. #include <exec/memory.h>
  26. #include <dos/dosextens.h>
  27. #include <dos/filehandler.h>
  28. #include <devices/scsidisk.h>
  29.  
  30. /*
  31. ** structure definitions now!
  32. */
  33.  
  34. struct PortIO {
  35.   struct IOStdReq req;
  36.   struct MsgPort  port;
  37. };
  38.  
  39. /*
  40. ** sizeof(struct Globals) _MUST_ be a multiple of 4 !
  41. */
  42.  
  43. struct Globals {
  44.  
  45.   /*** library stuff ***/
  46.  
  47.   struct ExecBase      *SysBase;
  48.   struct DosLibrary    *DosBase;
  49.  
  50.   /*** io stuff ***/
  51.  
  52.   STRPTR                ScsiName;
  53.   ULONG                 ScsiUnit;
  54.   struct PortIO        *ScsiIO;
  55.   struct SCSICmd        ScsiCmd;
  56.   UBYTE                 Pad[2],
  57.                        *ScsiData,
  58.                        *SenseBuf,
  59.                        *TocBuf,
  60.                         Command[12];
  61.   LONG                  HaveCmd,
  62.                         Arg1,Arg2;
  63. };
  64.  
  65. /*
  66. ** ptr to the `global' data space (will be on the stack :-)
  67. */
  68.  
  69. register struct Globals *gb asm("a4");
  70.  
  71. /*
  72. ** redirect global library bases to the `global' data space
  73. */
  74.  
  75. #define BASE_NAME gb->SysBase
  76. #include <proto/exec.h>
  77. #undef BASE_NAME
  78.  
  79. #define BASE_NAME gb->DosBase
  80. #include <proto/dos.h>
  81. #undef BASE_NAME
  82.  
  83. /*
  84. ** strcpy() && strlen()
  85. */
  86.  
  87. #include <string.h>
  88.  
  89. /*
  90. ** SCSI-2 stuff (taken from the ANSI draft, ct 11/1993 and SCSIutil)
  91. */
  92.  
  93. #include "cdt_scsi.h"
  94.  
  95. /***************************************************************************/
  96. /*                                                                         */
  97. /* prototypes                                                              */
  98. /*                                                                         */
  99. /***************************************************************************/
  100.  
  101. struct PortIO *OpenSCSI(STRPTR,ULONG);
  102. LONG GetBuffers();
  103. LONG GetArguments();
  104. VOID Main();
  105. LONG StartAudioPlay(LONG,LONG);
  106. LONG PauseResumePlay(LONG);
  107. VOID ShowInfo();
  108. LONG DoScsiCmd(UBYTE *,LONG,UBYTE *,LONG,LONG);
  109. VOID FreeBuffers();
  110. VOID CloseSCSI(struct PortIO *);
  111. VOID PrintF(STRPTR,...);
  112.  
  113. /***************************************************************************/
  114. /*                                                                         */
  115. /* ReadArgs() peculiarities + other defines                                */
  116. /*                                                                         */
  117. /***************************************************************************/
  118.  
  119. enum {
  120.   DEVICEARG=0,UNITARG,STARTTRACKARG,STARTINDEXARG,LASTTRACKARG,LASTINDEXARG,
  121.   LOADARG,EJECTARG,LOCKARG,UNLOCKARG,PLAYARG,STOPARG,PAUSEARG,RESUMEARG,
  122.   INFOARG,MAXARG
  123. };
  124.  
  125. #define TEMPLATE "D=DEVICE,U=UNIT/K/N,STARTTRACK/N,STARTINDEX/N,LASTTRACK/N," \
  126.                  "LASTINDEX/N,LOAD/S,EJECT/S,LOCK/S,UNLOCK/S,PLAY/S,STOP/S,"  \
  127.                  "PAUSE/S,RESUME/S,INFO/S"
  128.  
  129. #define DEFDEVICE "scsi.device"
  130. #define DEFUNIT   4
  131.  
  132. #define NEWLIST(l) ((l)->lh_Head = (struct Node *)&(l)->lh_Tail, \
  133.                     /*(l)->lh_Tail = NULL,*/ \
  134.                     (l)->lh_TailPred = (struct Node *)&(l)->lh_Head)
  135.  
  136. /***************************************************************************/
  137. /*                                                                         */
  138. /* memory clear function (!!! caution: size _MUST_ be a multiple of 4!!!)  */
  139. /*                                                                         */
  140. /***************************************************************************/
  141.  
  142. STATIC INLINE VOID MEMZEROL(VOID *mem,ULONG size)
  143. { ULONG *p;
  144.   WORD s;
  145.  
  146.   for(p=(ULONG *)mem,s=(size/sizeof(ULONG))-1; s>=0; *p++=NULL,s--);
  147. }
  148.  
  149. /***************************************************************************/
  150. /*                                                                         */
  151. /* implementation                                                          */
  152. /*                                                                         */
  153. /***************************************************************************/
  154.  
  155. LONG Start()
  156. {
  157.   struct Globals globals;
  158.  
  159.   MEMZEROL(&globals,sizeof(struct Globals)); gb = &globals;
  160.  
  161.   gb->SysBase = *(struct ExecBase **)4L;
  162.  
  163.   Main();
  164.  
  165.   return 0;
  166. }
  167.  
  168. /***************************************************************************/
  169. /*                                                                         */
  170. /* version string                                                          */
  171. /*                                                                         */
  172. /***************************************************************************/
  173.  
  174. CONST UBYTE verstag[]="$VER: CDT 1.0 (8.11.95) © 1995 by G.Nikl";
  175.  
  176. /***************************************************************************/
  177. /*                                                                         */
  178. /* open scsi device                                                        */
  179. /*                                                                         */
  180. /***************************************************************************/
  181.  
  182. struct PortIO *OpenSCSI(STRPTR DeviceName,ULONG DeviceUnit)
  183. {
  184.   struct PortIO *portio;
  185.  
  186.   if ((portio=(struct PortIO *)AllocMem(sizeof(struct PortIO),MEMF_CLEAR|MEMF_PUBLIC)))
  187.   {
  188.     portio->port.mp_Node.ln_Type=NT_MSGPORT;
  189.     if ((BYTE)(portio->port.mp_SigBit=AllocSignal(-1))>=0)
  190.     {
  191.       portio->port.mp_SigTask=FindTask(NULL);
  192.       NEWLIST(&portio->port.mp_MsgList);
  193.       portio->req.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  194.       portio->req.io_Message.mn_ReplyPort=&portio->port;
  195.       if (!(OpenDevice(DeviceName,DeviceUnit,(struct IORequest *)&portio->req,0)))
  196.         return portio;
  197.       FreeSignal(portio->port.mp_SigBit);
  198.     }
  199.     FreeMem(portio,sizeof(struct PortIO)); portio=NULL;
  200.   }
  201.   return portio;
  202. }
  203.  
  204. /***************************************************************************/
  205. /*                                                                         */
  206. /* allocate all buffers                                                    */
  207. /*                                                                         */
  208. /***************************************************************************/
  209.  
  210. LONG GetBuffers()
  211. {
  212.   LONG ret=0;
  213.  
  214.   if ((gb->ScsiData=AllocMem(DATALEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
  215.     if ((gb->SenseBuf=AllocMem(SENSELEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
  216.       if ((gb->TocBuf=AllocMem(TOCLEN,MEMF_CHIP|MEMF_PUBLIC)) != NULL)
  217.         ret=1;
  218.   return ret;
  219. }
  220.  
  221. /***************************************************************************/
  222. /*                                                                         */
  223. /* read arguments                                                          */
  224. /*                                                                         */
  225. /***************************************************************************/
  226.  
  227. LONG GetArguments()
  228. {
  229.   struct FileSysStartupMsg *fssm;
  230.   struct DosList *dol;
  231.   struct RDArgs *rda;
  232.   STRPTR name,p;
  233.   ULONG unit;
  234.   LONG args[MAXARG],size,tmp,value,i,*ptr,ret=0;
  235.  
  236.   MEMZEROL(&args[0],sizeof(args));
  237.   if ((rda=ReadArgs(TEMPLATE,&args[0],NULL)) != NULL)
  238.   {
  239.     i=MAXARG-LOADARG; ptr=&args[LOADARG];
  240.     do {} while(!(gb->HaveCmd=*ptr++) && --i);
  241.  
  242.     if (args[UNLOCKARG] || args[LOCKARG])
  243.     {
  244.       gb->Command[0] = SCSI_CMD_PAMR;
  245.       gb->Command[4] = (args[LOCKARG] ? 1 : 0);
  246.     }
  247.  
  248.     if (args[EJECTARG] || args[LOADARG])
  249.     {
  250.       gb->Command[0] = SCSI_CMD_SSU;
  251.       gb->Command[4] = (args[LOADARG] ? 1 : 0) + 2;
  252.     }
  253.  
  254.     if (args[PAUSEARG] || args[RESUMEARG])
  255.     {
  256.       gb->Command[0] = SCSI_CMD_RQS;
  257.       gb->Command[4] = SENSELEN;
  258.       ((UBYTE *)&gb->Arg1)[3] = (args[RESUMEARG] ? 1 : 0);
  259.     }
  260.  
  261.     if (args[STOPARG])
  262.     {
  263.       gb->Command[0] = SCSI_CMD_SSU;
  264.       gb->Command[4] = 0;
  265.     }
  266.  
  267.     if (!args[INFOARG] && args[PLAYARG])
  268.     {
  269.       gb->Command[0] = SCSI_CMD_PLAYAUDIOTRACKINDEX;
  270.  
  271.       value = 1;
  272.       if (args[STARTTRACKARG])
  273.       {
  274.         tmp = *(LONG *)args[STARTTRACKARG];
  275.         if (tmp > 0 && tmp < 100)
  276.           value = tmp;
  277.       }
  278.       gb->Command[4] = value; gb->Arg1 = value;
  279.  
  280.       value = 0;
  281.       if (args[STARTINDEXARG])
  282.       {
  283.         tmp = *(LONG *)args[STARTINDEXARG];
  284.         if (tmp >= 0 && tmp < 100)
  285.           value = tmp;
  286.       }
  287.       gb->Command[5] = value;
  288.  
  289.       value = 99;
  290.       if (args[LASTTRACKARG])
  291.       {
  292.         tmp = *(LONG *)args[LASTTRACKARG];
  293.         if (tmp > 0 && tmp < 100 && tmp > gb->Arg1)
  294.           value = tmp;
  295.       }
  296.       gb->Command[7] = value; gb->Arg2 = value;
  297.  
  298.       value = 0;
  299.       if (args[LASTINDEXARG])
  300.       {
  301.         tmp = *(LONG *)args[LASTINDEXARG];
  302.         if (tmp >= 0 && tmp < 100)
  303.           value = tmp;
  304.       }
  305.       gb->Command[8] = value;
  306.     }
  307.  
  308.     if (args[INFOARG])
  309.     {
  310.       gb->Command[0] = SCSI_CMD_INQ;
  311.       gb->Command[4] = DATALEN;
  312.     }
  313.  
  314.     unit = DEFUNIT;
  315.     if (args[UNITARG])
  316.       unit = *(ULONG *)args[UNITARG];
  317.     gb->ScsiUnit=unit;
  318.  
  319.     name = DEFDEVICE;
  320.     if (args[DEVICEARG])
  321.       name = (STRPTR)args[DEVICEARG];
  322.     if ((size=((tmp=strlen(name))+1+3)&~3) < 256)
  323.       size = 256;
  324.     if ((gb->ScsiName=AllocVec(size,MEMF_ANY)) != NULL)
  325.     {
  326.       name=strcpy(gb->ScsiName,name);
  327.       if (name[tmp-1] == ':')
  328.       {
  329.         name[tmp-1] = '\0';
  330.         dol=FindDosEntry(LockDosList(LDF_READ|LDF_DEVICES),name,LDF_DEVICES);
  331.         name[0] = '\0';
  332.         if (dol != NULL)
  333.         {
  334.           fssm=(struct FileSysStartupMsg *)BADDR(dol->dol_misc.dol_handler.dol_Startup);
  335.           if (TypeOfMem(fssm))
  336.           {
  337.             if (TypeOfMem((p=BADDR(fssm->fssm_Device))))
  338.             {
  339.               strcpy(name,1+p); gb->ScsiUnit = fssm->fssm_Unit;
  340.             }
  341.           }
  342.         }
  343.         UnLockDosList(LDF_READ|LDF_DEVICES);
  344.         if (name[0] == '\0')
  345.           strcpy(name,DEFDEVICE);
  346.       }
  347.       ret = 1;
  348.     }
  349.     FreeArgs(rda);
  350.   }
  351.   else
  352.     PrintFault(IoErr(),NULL);
  353.   return ret;
  354. }
  355.  
  356. /***************************************************************************/
  357. /*                                                                         */
  358. /* main function                                                           */
  359. /*                                                                         */
  360. /***************************************************************************/
  361.  
  362. #define CmdLen (gb->Command[0] != SCSI_CMD_PLAYAUDIOTRACKINDEX ? 6 : 10)
  363.  
  364. VOID Main()
  365. {
  366.   LONG err;
  367.  
  368.   if ((gb->DosBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) != NULL)
  369.   {
  370.     if (GetArguments())
  371.     {
  372.       if (GetBuffers())
  373.       {
  374.         if ((gb->ScsiIO=OpenSCSI(gb->ScsiName,gb->ScsiUnit)) != NULL)
  375.         {
  376.           if (gb->HaveCmd)
  377.           {
  378.             err = DoScsiCmd(gb->ScsiData,DATALEN,&gb->Command[0],CmdLen,(SCSIF_READ|SCSIF_AUTOSENSE));
  379.  
  380.             if (err != 0 && gb->Command[0] == SCSI_CMD_PLAYAUDIOTRACKINDEX)
  381.               err = StartAudioPlay(gb->Arg1,gb->Arg2);
  382.             else
  383.               switch (gb->Command[0])
  384.               {
  385.                 case SCSI_CMD_RQS:
  386.                   err = PauseResumePlay(gb->Arg1);
  387.                   break;
  388.                 case SCSI_CMD_INQ:
  389.                   ShowInfo();
  390.                 default:
  391.                   break;
  392.               }
  393.  
  394.             if (err != 0 && gb->ScsiCmd.scsi_SenseActual >= OFFS_KEY)
  395.               PrintF("direct command failed! (Sense: 0x%02lx, Code: 0x%02lx, Qualifier: 0x%02lx)\n",
  396.                      (LONG)gb->SenseBuf[OFFS_KEY]&0xf,(LONG)gb->SenseBuf[OFFS_CODE],(LONG)gb->SenseBuf[OFFS_QUAL]);
  397.           }
  398.           CloseSCSI(gb->ScsiIO);
  399.         }
  400.         else
  401.           PrintF("couldn't open `%s' unit `%ld'\n",gb->ScsiName,gb->ScsiUnit);
  402.       }
  403.       FreeBuffers();
  404.       FreeVec(gb->ScsiName);
  405.     }
  406.     CloseLibrary(&(gb->DosBase->dl_lib));
  407.   }
  408. }
  409.  
  410. /***************************************************************************/
  411. /*                                                                         */
  412. /* PlayAudioTrackIndex (0x48) failed so try it with another play command   */
  413. /*                                                                         */
  414. /***************************************************************************/
  415.  
  416. LONG StartAudioPlay(LONG First,LONG Last)
  417. {
  418.   UBYTE *data,*toc;
  419.   LONG err,tmp,index;
  420.  
  421.   data=&gb->Command[0];
  422.  
  423.   *(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
  424.  
  425.   data[0] = SCSI_CMD_READTOC;
  426.   data[7] = ((TOCLEN >> 8) & 0xFF);
  427.   data[8] = ((TOCLEN >> 0) & 0xFF);
  428.  
  429.   if ((err=DoScsiCmd(gb->TocBuf,TOCLEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE))) == 0)
  430.   {
  431.     toc=gb->TocBuf;
  432.  
  433.     if ((tmp=toc[3]) < Last)
  434.       if ((Last=tmp) < First)
  435.         First = 1;
  436.  
  437.     data[0] = SCSI_CMD_PLAYAUDIO12;
  438.  
  439.     index = 8*First;
  440.     First = 1 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
  441.     data[2] = ((First >> 24) & 0xFF);
  442.     data[3] = ((First >> 16) & 0xFF);
  443.     data[4] = ((First >>  8) & 0xFF);
  444.     data[5] = ((First >>  0) & 0xFF);
  445.  
  446.     index = 8*Last+8;
  447.     Last = -2 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
  448.     Last -= First;
  449.     data[6] = ((Last >> 24) & 0xFF);
  450.     data[7] = ((Last >> 16) & 0xFF);
  451.     data[8] = ((Last >>  8) & 0xFF);
  452.     data[9] = ((Last >>  0) & 0xFF);
  453.  
  454.     err = DoScsiCmd(gb->ScsiData,DATALEN,data,12,(SCSIF_READ|SCSIF_AUTOSENSE));
  455.   }
  456.   return err;
  457. }
  458.  
  459. /***************************************************************************/
  460. /*                                                                         */
  461. /* Pause / Resume audio play (REQUEST SENSE was done before)               */
  462. /*                                                                         */
  463. /***************************************************************************/
  464.  
  465. LONG PauseResumePlay(LONG What)
  466. {
  467.   UBYTE *data = gb->ScsiData;
  468.   LONG audio,err = 0;
  469.  
  470.   if ((BYTE)(data[OFFS_KEY]&0xf) == 0)
  471.   {
  472.     audio = data[OFFS_QUAL];
  473.  
  474.     if ((audio == 0x11 && What == 0) || (audio == 0x12 && What == 1))
  475.     {
  476.       data=&gb->Command[0];
  477.  
  478.       *(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
  479.  
  480.       data[0] = SCSI_CMD_PAUSERESUME;
  481.       data[8] = What;
  482.  
  483.       err = DoScsiCmd(gb->ScsiData,DATALEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE));
  484.     }
  485.   }
  486.   return err;
  487. }
  488.  
  489. /***************************************************************************/
  490. /*                                                                         */
  491. /* display inquiry information                                             */
  492. /*                                                                         */
  493. /***************************************************************************/
  494.  
  495. CONST UBYTE *CONST DeviceType[] = {
  496.   "Direct-access device (e.g., magnetic disk)",
  497.   "Sequential-access device (e.g., magnetic tape)",
  498.   "Printer device",
  499.   "Processor device",
  500.   "Write-once device (e.g., some optical disks)",
  501.   "CD-ROM device",
  502.   "Scanner device",
  503.   "Optical memory device (e.g., some optical disks)",
  504.   "Medium Changer device (e.g., jukeboxes)",
  505.   "Communications device",
  506.   "Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
  507.   "Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
  508.   "Reserved, unknown or no device type"
  509. };
  510.  
  511. CONST UBYTE *CONST AnsiVersion[] = {
  512.   "The device might or might not comply to an ANSI-approved standard.",
  513.   "The device complies to ANSI X3.131-1986 (SCSI-1).",
  514.   "The device complies to ANSI X?.???-???? (SCSI-2).",
  515.   "Reserved",
  516. };
  517.  
  518. CONST UBYTE *CONST ResponseFormat[] = {
  519.   "SCSI-1",
  520.   "CCS",
  521.   "SCSI-2",
  522.   "Reserved",
  523. };
  524.  
  525. CONST UBYTE *CONST DataTransfer[] = {
  526.   "8-bit only",
  527.   "16-bit",
  528.   "32-bit",
  529.   "16 and 32-bit"
  530. };
  531.  
  532. VOID ShowInfo()
  533. {
  534.   UBYTE *data=gb->ScsiData;
  535.   STRPTR p1,p2;
  536.   ULONG index;
  537.  
  538.   if ((index=data[0]&0x1f) > 0x0b)
  539.     index = 0x0c;
  540.   PrintF("Device type          : %s\n",DeviceType[index]);
  541.  
  542.   if ((index=data[2]&0x07) > 0x02)
  543.     index = 0x03;
  544.   PrintF("ANSI-approved version: %s\n",AnsiVersion[index]);
  545.  
  546.   if ((index=data[3]&0x0f) > 0x02)
  547.     index = 0x03;
  548.   PrintF("Response data format : %s\n",ResponseFormat[index]);
  549.  
  550.   PrintF("Vendor               : %.8s\n",&data[8]);
  551.   PrintF("Product              : %.16s\n",&data[16]);
  552.   PrintF("Revision             : %.4s\n",&data[32]);
  553.  
  554.   index = (data[7]&0x60)>>5;
  555.   PrintF("Transfer             : %s\n",DataTransfer[index]);
  556.  
  557.   p1 = "not removable"; p2 = p1 + 4;
  558.   PrintF("Medium               : %s\n",(data[1]&0x80 ? p2 : p1));
  559.  
  560.   p1 = "not supported"; p2 = p1 + 4;
  561.   PrintF("Relative addressing  : %s\n",(data[7]&0x80 ? p2 : p1));
  562.   PrintF("Synchronous transfer : %s\n",(data[7]&0x10 ? p2 : p1));
  563.   PrintF("Linked command       : %s\n",(data[7]&0x08 ? p2 : p1));
  564.   PrintF("Command queuing      : %s\n",(data[7]&0x02 ? p2 : p1));
  565.   PrintF("Soft reset           : %s\n",(data[7]&0x01 ? p2 : p1));
  566. }
  567.  
  568. /***************************************************************************/
  569. /*                                                                         */
  570. /* issue a scsi command                                                    */
  571. /*                                                                         */
  572. /***************************************************************************/
  573.  
  574. LONG DoScsiCmd(UBYTE *data,LONG datasize,UBYTE *cmd,LONG cmdsize,LONG flags)
  575. {
  576.   struct PortIO *portio;
  577.   struct SCSICmd *scmd;
  578.  
  579.   portio = gb->ScsiIO;
  580.   portio->req.io_Command = HD_SCSICMD;
  581.   scmd = &gb->ScsiCmd;
  582.   portio->req.io_Data    = (APTR)scmd;
  583.   portio->req.io_Length  = sizeof(struct SCSICmd);
  584.  
  585.   scmd->scsi_Data        = (APTR)data;
  586.   scmd->scsi_Length      = datasize;
  587.   scmd->scsi_SenseActual = 0;
  588.   scmd->scsi_SenseData   = gb->SenseBuf;
  589.   scmd->scsi_SenseLength = SENSELEN;
  590.   scmd->scsi_Command     = cmd;
  591.   scmd->scsi_CmdLength   = cmdsize;
  592.   scmd->scsi_Flags       = flags;
  593.  
  594.   DoIO((struct IORequest *)&portio->req);
  595.  
  596.   return portio->req.io_Error;
  597. }
  598.  
  599. /***************************************************************************/
  600. /*                                                                         */
  601. /* free all buffers                                                        */
  602. /*                                                                         */
  603. /***************************************************************************/
  604.  
  605. VOID FreeBuffers()
  606. {
  607.   APTR buf;
  608.  
  609.   if ((buf=gb->TocBuf) != NULL)
  610.     FreeMem(buf,TOCLEN);
  611.   if ((buf=gb->SenseBuf) != NULL)
  612.     FreeMem(buf,SENSELEN);
  613.   if ((buf=gb->ScsiData) != NULL)
  614.     FreeMem(buf,DATALEN);
  615. }
  616.  
  617. /***************************************************************************/
  618. /*                                                                         */
  619. /* close scsi device                                                       */
  620. /*                                                                         */
  621. /***************************************************************************/
  622.  
  623. VOID CloseSCSI(struct PortIO *portio)
  624. {
  625.   CloseDevice((struct IORequest *)&portio->req);
  626.   FreeSignal(portio->port.mp_SigBit);
  627.   FreeMem(portio,sizeof(struct PortIO));
  628. }
  629.  
  630. /***************************************************************************/
  631. /*                                                                         */
  632. /* vararg printf() with VPrintf() from the dos.library (can't use Printf())*/
  633. /*                                                                         */
  634. /***************************************************************************/
  635.  
  636. VOID PrintF(STRPTR format,...)
  637. {
  638.   VPrintf(format,(APTR)(&format+1));
  639. }
  640.  
  641. /***************************************************************************/
  642. /*                                                                         */
  643. /* The End                                                                 */
  644. /*                                                                         */
  645. /***************************************************************************/
  646.